imports

library(tidyr)
library(pspline)
library(purrr)
library(dplyr)
library(ggplot2)
library(RColorBrewer)
library(reshape2)
library(TTR)
require(smooth)
require(greybox)
require(Mcomp)
library(RColorBrewer)
library(forecast)
add_loess <- function(df){
  loess_df <- data.frame(df$timestamps)
  for(i in names(df)){
    if(grepl('absolute', i) & !grepl('loess', i)){
      name <- paste("loess_", i, sep = "")
      df[, name] <- loess(df[,i] ~ df$timestamps, data = df, span=0.65)$fitted
    }
  }
  return(df)
}
add_average <- function(df, wave){
  name <- paste("avg_", wave, sep = "")
  temp_df <- df[,names(df) %in% colnames(df)[grepl(wave,colnames(df)) & !grepl("loess",colnames(df)) & !grepl("1",colnames(df)) & !grepl("4",colnames(df))]]
  temp_avg <- rowMeans(temp_df, dims = 1)
  df[, name] <- temp_avg
  return(df)
}

load data

inexp_meditation_files = sort(list.files("ffted/",pattern="^0_ffted_med"))
inexp_reference_files = sort(list.files("ffted/",pattern="^0_ffted_ref"))
exp_meditation_files = sort(list.files("ffted/",pattern="^1_ffted_med"))
exp_reference_files = sort(list.files("ffted/",pattern="^1_ffted_ref"))
exp_meditation = list()
for(i in 1:length(exp_meditation_files)) {
  file = exp_meditation_files[i]
  exp_meditation[[i]] <- read.csv(paste("ffted/", file, sep=""))
  exp_meditation[[i]] <- exp_meditation[[i]][rowSums(exp_meditation[[i]] == "-Inf") == 0, , drop = FALSE]
  exp_meditation[[i]] <- add_average(exp_meditation[[i]], "alpha")
  exp_meditation[[i]] <- add_average(exp_meditation[[i]], "beta")
  exp_meditation[[i]] <- add_average(exp_meditation[[i]], "gamma")
  exp_meditation[[i]] <- add_average(exp_meditation[[i]], "delta")
  exp_meditation[[i]] <- add_average(exp_meditation[[i]], "theta")
  exp_meditation[[i]] <- add_loess(exp_meditation[[i]])
}
inexp_meditation = list()
for(i in 1:length(inexp_meditation_files)) {
  file = inexp_meditation_files[i]
  inexp_meditation[[i]] <-  read.csv(paste("ffted/", file, sep=""))
  inexp_meditation[[i]] <- inexp_meditation[[i]][rowSums(inexp_meditation[[i]] == "-Inf") == 0, , drop = FALSE]
  inexp_meditation[[i]] <- add_average(inexp_meditation[[i]], "alpha")
  inexp_meditation[[i]] <- add_average(inexp_meditation[[i]], "beta")
  inexp_meditation[[i]] <- add_average(inexp_meditation[[i]], "gamma")
  inexp_meditation[[i]] <- add_average(inexp_meditation[[i]], "delta")
  inexp_meditation[[i]] <- add_average(inexp_meditation[[i]], "theta")
  inexp_meditation[[i]] <- add_loess(inexp_meditation[[i]])
}
exp_reference = list()
for(i in 1:length(exp_reference_files)) {
  file = exp_reference_files[i]
  exp_reference[[i]] <-  read.csv(paste("ffted/", file, sep=""))
  exp_reference[[i]] <- exp_reference[[i]][rowSums(exp_reference[[i]] == "-Inf") == 0, , drop = FALSE]
  exp_reference[[i]] <- add_average(exp_reference[[i]], "alpha")
  exp_reference[[i]] <- add_average(exp_reference[[i]], "beta")
  exp_reference[[i]] <- add_average(exp_reference[[i]], "gamma")
  exp_reference[[i]] <- add_average(exp_reference[[i]], "delta")
  exp_reference[[i]] <- add_average(exp_reference[[i]], "theta")
  exp_reference[[i]] <- add_loess(exp_reference[[i]])
}
inexp_reference = list()
for(i in 1:length(inexp_reference_files)) {
  file = inexp_reference_files[i]
  inexp_reference[[i]] <-  read.csv(paste("ffted/", file, sep=""))
  inexp_reference[[i]] <- inexp_reference[[i]][rowSums(inexp_reference[[i]] == "-Inf") == 0, , drop = FALSE]
  inexp_reference[[i]] <- add_average(inexp_reference[[i]], "alpha")
  inexp_reference[[i]] <- add_average(inexp_reference[[i]], "beta")
  inexp_reference[[i]] <- add_average(inexp_reference[[i]], "gamma")
  inexp_reference[[i]] <- add_average(inexp_reference[[i]], "delta")
  inexp_reference[[i]] <- add_average(inexp_reference[[i]], "theta")
  inexp_reference[[i]] <- add_loess(inexp_reference[[i]])
}

convert time from absolute to relative

convert_time <- function(timestamps){
  time <- timestamps - min(timestamps)
  return(time)
}

subsetting data

subset_and_melt <- function(med, exp, wave, electrodes, melt, melt_all){
  if(med){
    if(exp){
      df <- exp_meditation
    }
    else{
      df <- inexp_meditation
    }
  }
  else{
    if(exp){
      df <- exp_reference
    }
    else{
      df <- inexp_reference
    }
  }
  data = list()
  for(i in 1:length(df)) {
  data[[i]] <- df[[i]][, grepl(paste('(', wave, ')|(', electrodes, ')|(timestamp)', sep = ""), names(df[[i]]))]
  data[[i]]$timestamps <- convert_time(data[[i]]$timestamps)
  if(melt){
    data[[i]] <- melt(data[[i]], id.vars = 'timestamps', variable.name = 'waves')
    data[[i]]$waves <- as.factor(data[[i]]$waves)
  }
  }
  if(melt_all){
    data <- melt(data, id.vars = c('timestamps', 'waves', 'value'))
    data$L1 <- as.factor(data$L1)
  }
  
  return(data)
}

testing

temp_2 <- subset_and_melt(FALSE, TRUE, "beta", "None", TRUE, TRUE)
#ggplot(temp_2[[1]], aes(timestamps,value)) + geom_line(aes(colour = waves))

things to think about: * extreme points, spikes, etc * different smoothing rate * difference between meditative and regular state * difference between experienced meditators and newbies * how to determine the levels and scale it for others * what happens when meditation is stable * explore the coherence between alpha and theta waves

explore experienced/inexperienced distributions of alpha wave

alpha_exp_med = subset_and_melt(TRUE, TRUE, 'alpha', 'ALL', TRUE, TRUE)
alpha_inexp_med = subset_and_melt(TRUE, FALSE, 'alpha', 'ALL', TRUE, TRUE)
alpha_exp_med$exp <- "experienced"
alpha_exp_med$exp <- as.factor(alpha_exp_med$exp)
alpha_inexp_med$exp <- "inexperienced"
alpha_inexp_med$exp <- as.factor(alpha_inexp_med$exp)
temp <- rbind(alpha_exp_med, alpha_inexp_med)
ggplot(temp, aes(value, fill = exp)) + 
  geom_histogram(alpha = 0.5, bins = 100, position = 'identity')

explore experienced/inexperienced distributions of theta wave

theta_exp_med = subset_and_melt(TRUE, TRUE, 'theta', 'ALL', TRUE, TRUE)
theta_inexp_med = subset_and_melt(TRUE, FALSE, 'theta', 'ALL', TRUE, TRUE)
theta_exp_med$exp <- "experienced"
theta_exp_med$exp <- as.factor(theta_exp_med$exp)
theta_inexp_med$exp <- "inexperienced"
theta_inexp_med$exp <- as.factor(theta_inexp_med$exp)
temp <- rbind(theta_exp_med, theta_inexp_med)
ggplot(temp, aes(value, fill = exp)) + 
  geom_histogram(alpha = 0.5, bins = 100, position = 'identity')

explore experienced/inexperienced distributions of beta wave

beta_exp_med = subset_and_melt(TRUE, TRUE, 'beta', 'ALL', TRUE, TRUE)
beta_inexp_med = subset_and_melt(TRUE, FALSE, 'beta', 'ALL', TRUE, TRUE)
beta_exp_med$exp <- "experienced"
beta_exp_med$exp <- as.factor(beta_exp_med$exp)
beta_inexp_med$exp <- "inexperienced"
beta_inexp_med$exp <- as.factor(beta_inexp_med$exp)
temp <- rbind(beta_exp_med, beta_inexp_med)
ggplot(temp, aes(value, fill = exp)) + 
  geom_histogram(alpha = 0.5, bins = 100, position = 'identity')

explore experienced/inexperienced distributions of gamma wave

gamma_exp_med = subset_and_melt(TRUE, TRUE, 'gamma', 'ALL', TRUE, TRUE)
gamma_inexp_med = subset_and_melt(TRUE, FALSE, 'gamma', 'ALL', TRUE, TRUE)
gamma_exp_med$exp <- "experienced"
gamma_exp_med$exp <- as.factor(gamma_exp_med$exp)
gamma_inexp_med$exp <- "inexperienced"
gamma_inexp_med$exp <- as.factor(gamma_inexp_med$exp)
temp <- rbind(gamma_exp_med, gamma_inexp_med)
ggplot(temp, aes(value, fill = exp)) + 
  geom_histogram(alpha = 0.5, bins = 100, position = 'identity')

explore experienced/inexperienced distributions of delta wave

t.test(na.omit(alpha_exp_med$value), na.omit(alpha_inexp_med$value), var.equal = TRUE)

    Two Sample t-test

data:  na.omit(alpha_exp_med$value) and na.omit(alpha_inexp_med$value)
t = 101.66, df = 685930, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.2013323 0.2092484
sample estimates:
mean of x mean of y 
0.9737287 0.7684384 
t.test(na.omit(alpha_exp_med$value), na.omit(alpha_inexp_med$value), var.equal = TRUE)

    Two Sample t-test

data:  na.omit(alpha_exp_med$value) and na.omit(alpha_inexp_med$value)
t = 161.49, df = 1543400, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.2040037 0.2090164
sample estimates:
mean of x mean of y 
0.9426494 0.7361393 
t_test <- function(wave, med){
  wave_exp <- subset_and_melt(med, TRUE, wave, "All", TRUE, FALSE)
  medians_exp <- list()
  for(i in 1:length(wave_exp)){
    medians_exp[[i]] <- median(wave_exp[[i]]$value)
  }
  wave_inexp <- subset_and_melt(med, FALSE, wave, "All", TRUE, FALSE)
  medians_inexp <- list()
  for(i in 1:length(wave_inexp)){
    medians_inexp[[i]] <- median(wave_inexp[[i]]$value)
  }
  
  medians_exp <- unlist(medians_exp, use.names=FALSE)
  medians_inexp <- unlist(medians_inexp, use.names=FALSE)
  return(print(t.test(medians_exp, medians_inexp)))
}
a <- t_test("beta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -0.18003, df = 7.7255, p-value = 0.8618
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.4753273  0.4068778
sample estimates:
mean of x mean of y 
0.8503494 0.8845742 
a <- t_test("gamma", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -0.43366, df = 7.0362, p-value = 0.6775
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.5995961  0.4135896
sample estimates:
mean of x mean of y 
0.4898110 0.5828143 
a <- t_test("delta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.76505, df = 9.4431, p-value = 0.4629
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.2353533  0.4785046
sample estimates:
mean of x mean of y 
0.3027340 0.1811583 
a <- t_test("theta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.57218, df = 12.632, p-value = 0.5772
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.2152788  0.3697712
sample estimates:
mean of x mean of y 
0.7990211 0.7217749 
a <- t_test("theta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.51721, df = 12.545, p-value = 0.614
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.2674452  0.4349945
sample estimates:
mean of x mean of y 
0.7675215 0.6837468 

There is no significant statistical difference in medians and means between experienced and inexperienced people

t_test_min <- function(wave, med){
  wave_exp <- subset_and_melt(med, TRUE, wave, "All", TRUE, FALSE)
  medians_exp <- list()
  for(i in 1:length(wave_exp)){
    medians_exp[[i]] <- min(wave_exp[[i]]$value)
  }
  wave_inexp <- subset_and_melt(med, FALSE, wave, "All", TRUE, FALSE)
  medians_inexp <- list()
  for(i in 1:length(wave_inexp)){
    medians_inexp[[i]] <- min(wave_inexp[[i]]$value)
  }
  
  medians_exp <- unlist(medians_exp, use.names=FALSE)
  medians_inexp <- unlist(medians_inexp, use.names=FALSE)
  return(print(t.test(medians_exp, medians_inexp)))
}
a <- t_test_min("alpha", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.40198, df = 9.0746, p-value = 0.697
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.8983212  1.2871653
sample estimates:
mean of x mean of y 
-1.197179 -1.391601 
a <- t_test_min("theta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.47281, df = 9.3345, p-value = 0.6472
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.8883717  1.3610984
sample estimates:
mean of x mean of y 
-1.227769 -1.464133 
a <- t_test_min("gamma", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.1358, df = 7.1696, p-value = 0.8957
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.9793947  1.0993536
sample estimates:
 mean of x  mean of y 
-0.8495856 -0.9095651 
a <- t_test_min("beta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = 0.34185, df = 8.3868, p-value = 0.7409
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.007439  1.361425
sample estimates:
 mean of x  mean of y 
-0.4808075 -0.6578005 
a <- t_test_min("delta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -0.17516, df = 12.919, p-value = 0.8637
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.486542  1.263703
sample estimates:
mean of x mean of y 
-4.062885 -3.951465 
t_test_max <- function(wave, med){
  wave_exp <- subset_and_melt(med, TRUE, wave, "All", TRUE, FALSE)
  medians_exp <- list()
  for(i in 1:length(wave_exp)){
    medians_exp[[i]] <- max(wave_exp[[i]]$value)
  }
  wave_inexp <- subset_and_melt(med, FALSE, wave, "All", TRUE, FALSE)
  medians_inexp <- list()
  for(i in 1:length(wave_inexp)){
    medians_inexp[[i]] <- max(wave_inexp[[i]]$value)
  }
  
  medians_exp <- unlist(medians_exp, use.names=FALSE)
  medians_inexp <- unlist(medians_inexp, use.names=FALSE)
  return(print(t.test(medians_exp, medians_inexp)))
}
a <- t_test_max("alpha", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -1.0657, df = 11.867, p-value = 0.3078
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.2699213  0.4363986
sample estimates:
mean of x mean of y 
 3.694748  4.111509 
a <- t_test_max("theta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -0.56219, df = 10.179, p-value = 0.5862
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.9047506  0.5394850
sample estimates:
mean of x mean of y 
 4.309198  4.491831 
a <- t_test_max("gamma", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -1.7215, df = 9.7672, p-value = 0.1166
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.6313428  0.2118538
sample estimates:
mean of x mean of y 
 3.275454  3.985199 
a <- t_test_max("beta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -1.5388, df = 8.1208, p-value = 0.1619
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.4203471  0.2816698
sample estimates:
mean of x mean of y 
 3.641218  4.210557 
a <- t_test_max("delta", TRUE)

    Welch Two Sample t-test

data:  medians_exp and medians_inexp
t = -0.13081, df = 12.048, p-value = 0.8981
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.9272460  0.8221727
sample estimates:
mean of x mean of y 
 4.311494  4.364031 
#ggplot(temp, aes(value, fill = exp)) + 
#  geom_histogram(alpha = 0.5, bins = 100, position = 'identity')
data_temp <- subset_and_melt(TRUE, TRUE, 'alpha', "ALL", TRUE, TRUE)
#geom_line(aes(y=theta_absolute_2, x = timestamps), 
#       data = without_na, color=brewer.pal(4, "Blues")[3]) + #geom_smooth(aes(y=theta_absolute_2, x = timestamps), 
#       data = without_na, color=brewer.pal(4, "Blues")[3], span = 0.01) +
#temps <- data_temp[data_temp$L1 == 1 & data_temp$waves == "alpha_absolute_1", ]
# data_temp$L1 == 1,
#data_temp$waves == "alpha_absolute_1", 
#data_temp <- data_temp[data_temp$L1 == 1,]
to_draw <- data_temp[data_temp$L1 == 1 & data_temp$waves == "alpha_absolute_1", ]
#ggplot(aes(y = value, x = timestamps), data = data_temp, data_temp$waves == "alpha_absolute_1") +
#ggplot() + 
#  geom_line(aes(SMA(to_draw$value, n=15), x = to_draw$timestamps))
#ggplot(aes(y = value, x = timestamps), data = data_temp, data_temp$waves == "alpha_absolute_1") +
  #geom_line() +
#  geom_smooth(span = 0.001, level = 0.95, method = 'loess') 
temp <- es(to_draw$value, h=18, holdout=TRUE, silent=FALSE)
The provided data is not ts object. Only non-seasonal models are available.
Only additive models are allowed with non-positive data.
Forming the pool of models based on... ANN, AAN, Estimation progress:    100%... Done! 

#to_draw_part$sma <- sma(to_draw_part$value, n = 5, v = 0.9)$fitted
to_draw_part$loess <- loess(value ~ timestamps, data=to_draw_part, span=0.65)$fitted
Error in is.data.frame(data) : object 'to_draw_part' not found

ggplot() +
  geom_line(aes(y = value, x = timestamps), data = to_draw_part) +
  geom_smooth(aes(y = value, x = timestamps), data = to_draw_part, span = 1, n = 15, color = "blue") +
  geom_line(aes(y = loess, x = timestamps), data = to_draw_part, color = 'red')
ggplot() +
  geom_smooth(aes(y = value, x = timestamps), data = theta_exp_med[theta_exp_med$waves == 'loess_theta_absolute_2',], span = 1, n = 15, color = "blue") +
  geom_line(aes(y = value, x = timestamps), data = theta_exp_med[theta_exp_med$waves == 'loess_theta_absolute_2',], color = 'red', alpha = 0.2) +
  geom_line(aes(y = value, x = timestamps), data = theta_exp_med[theta_exp_med$waves == 'theta_absolute_2',], color = 'black', alpha = 0.2)

curr_data <- theta_exp_med[theta_exp_med$L1 == '1',]
#[theta_exp_med$waves == 'theta_absolute_2' & 
    
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'red', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1)

temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
loess_ordered <- temp$value
loess_ordered <- sort(loess_ordered)
min(loess_ordered)
[1] 0.3447938
barplot(loess_ordered)

temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

NA

theta_2, second person

curr_data <- theta_exp_med[theta_exp_med$L1 == '2',]
temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

curr_data <- theta_exp_med[theta_exp_med$L1 == '3',]
temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

curr_data <- theta_exp_med[theta_exp_med$L1 == '4',]
temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

curr_data <- theta_exp_med[theta_exp_med$L1 == '6',]
temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

curr_data <- theta_exp_med[theta_exp_med$L1 == '7',]
temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

curr_data <- theta_exp_med[theta_exp_med$L1 == '8',]
temp <- curr_data[curr_data$waves == 'loess_theta_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'theta_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_theta_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

curr_data <- alpha_exp_med[theta_exp_med$L1 == '1',]
temp <- curr_data[curr_data$waves == 'loess_alpha_absolute_2', ]
temp$state <- cut(temp$value, quantile(temp$value,(0:5)/5))
ggplot(aes(y = value, x = timestamps), data = curr_data) +
  geom_line(data = curr_data[curr_data$waves == 'alpha_absolute_2', ], color = 'grey', alpha = 0.7) +
  geom_line(data = curr_data[curr_data$waves == 'loess_alpha_absolute_2',], color = 'black', alpha = 1) +
  geom_line(aes(y = value, x = timestamps, color = state, size = 2),data = temp, alpha = 1) 

alpha_2_all_exp <- subset_and_melt(TRUE, TRUE, 'alpha', 'All', TRUE, TRUE)
ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_2',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 2, exp")

alpha_2_all_exp <- subset_and_melt(TRUE, TRUE, 'alpha', 'All', TRUE, TRUE)
ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_1',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 1, exp")

alpha_2_all_exp <- subset_and_melt(TRUE, TRUE, 'alpha', 'All', TRUE, TRUE)
ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_3',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 3, exp")

alpha_2_all_exp <- subset_and_melt(TRUE, TRUE, 'alpha', 'All', TRUE, TRUE)
ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_4',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 4, exp")

alpha_2_all_exp <- subset_and_melt(TRUE, FALSE, 'alpha', 'All', TRUE, TRUE)
ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_2',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 2, inexp")

ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_1',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 1, inexp")

ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_3',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 3, inexp")

ggplot(aes(x = timestamps, y = value), data = alpha_2_all_exp[alpha_2_all_exp$waves == 'loess_alpha_absolute_4',]) +
  geom_line(aes(color = L1)) +
  ggtitle("alpha 4, inexp")

temp <- subset_and_melt(TRUE, TRUE, 'theta', 'All', TRUE, TRUE)
ggplot(aes(x = timestamps, y = value), data = temp[temp$waves == 'loess_theta_absolute_1',]) +
  geom_line(aes(color = L1)) +
  ggtitle("theta 1, exp")

ggplot(aes(x = timestamps, y = value), data = temp[temp$waves == 'loess_theta_absolute_2',]) +
  geom_line(aes(color = L1)) +
  ggtitle("theta 2, exp")

ggplot(aes(x = timestamps, y = value), data = temp[temp$waves == 'loess_theta_absolute_3',]) +
  geom_line(aes(color = L1)) +
  ggtitle("theta 3, exp")

ggplot(aes(x = timestamps, y = value), data = temp[temp$waves == 'loess_theta_absolute_4',]) +
  geom_line(aes(color = L1)) +
  ggtitle("theta 4, exp")

temp <- subset_and_melt(TRUE, TRUE, 'alpha', 'theta', TRUE, TRUE)
ggplot() +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_theta_absolute_1',],  size = 1) +
  ggtitle("theta 1 and alpha 1, exp") +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_alpha_absolute_1',], linetype = 'dotted', size = 1) +
  scale_color_brewer(palette = "Spectral")

ggplot() +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_theta_absolute_2',],  size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_alpha_absolute_2',], linetype = 'dotted', size = 1) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("theta 2 and alpha 2, exp")

ggplot() +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_theta_absolute_3',],  size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_alpha_absolute_3',], linetype = 'dotted', size = 1) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("theta 3 and alpha 3, exp")

ggplot() +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_theta_absolute_4',],  size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = temp[temp$waves == 'loess_alpha_absolute_4',], linetype = 'dotted', size = 1) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("theta 4 and alpha 4, exp")

alpha_with_averages <- subset_and_melt(TRUE, TRUE, 'alpha', 'all', TRUE, TRUE)
ggplot() +
  geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'alpha_absolute_2',],  size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'loess_alpha_absolute_2',], linetype = 'dotted', size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], linetype = 'dotted', size = 1) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("alpha 2 all together, exp")

ggplot() +
  #geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == #'loess_alpha_absolute_2',], linetype = 'dotted', size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], size = 1, alpha = 0.5) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("alpha averages")

ggplot() +
  #geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == #'loess_alpha_absolute_2',], linetype = 'dotted', size = 1) +
  geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], size = 1, alpha = 0.2) +
  scale_color_brewer(palette = "Spectral") +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], size = 1) +
  ggtitle("alpha averages with smoothing")

ggplot() +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], size = 0.5) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("alpha averages with smoothing")

ggplot() +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], size = 0.5) +
    geom_line(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'loess_alpha_absolute_2',], size = 1, alpha = 1) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("alpha averages with smoothing VS alpha 2 (bold)")

theta_with_averages <- subset_and_melt(TRUE, TRUE, 'theta', 'all', TRUE, TRUE)
ggplot() +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = theta_with_averages[theta_with_averages$waves == 'avg_theta',], size = 0.5) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("theta averages with smoothing")

ggplot() +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = theta_with_averages[theta_with_averages$waves == 'avg_theta',], size = 0.5) +
    geom_line(aes(x = timestamps, y = value, color = L1), data = theta_with_averages[theta_with_averages$waves == 'loess_theta_absolute_2',], size = 1, alpha = 1) +
  scale_color_brewer(palette = "Spectral") +
  ggtitle("theta averages with smoothing VS theta 2 (bold)")

ggplot() +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = theta_with_averages[theta_with_averages$waves == 'avg_theta',], size = 0.5) +
  geom_smooth(aes(x = timestamps, y = value, color = L1), data = alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',], size = 1) +
  
  scale_color_brewer(palette = "Spectral") +
  ggtitle("theta averages VS alpha averages (bold)")

split_stages <- function(df, time_interval, representative_period, threshold){
  current_time <- 0
  current_stage <- 1
  df$stages <- rep(0,nrow(df))
  df$stages[df$timestamps < current_time + time_interval] <- current_stage #first 3 minutes
  while(TRUE){
    if(current_time + time_interval + 1 > max(df$timestamps)){
      break
    }
    repr_df <- df[(df$timestamps < (current_time + time_interval) & df$timestamps > (current_time + time_interval - representative_period)),]
    new_stage_sign <- next_stage(repr_df, threshold) #defining a new stage level
    if(new_stage_sign > 0){
      current_stage <- min(current_stage + 1, 5)
    }
    if(new_stage_sign < 0){
      current_stage <- max(current_stage - 1, 1)
    }
    #set a new stage in the df
    df[(df$timestamps < (current_time + 2 * time_interval) & df$timestamps > (current_time + time_interval)),]$stages <- current_stage
    current_time <- current_time + time_interval
  }
  df$stages <- as.factor(df$stages)
  return(df$stages)
}
next_stage <- function(df, threshold){
  fit <- auto.arima(df$value)
  forecast <- predict(fit, length(df$value))
  initial_data <- df[(df$value < quantile(df$value, 0.95) & df$value > quantile(df$value, 0.05)), ]$value
  forecast <- forecast$pred
  forecast <- forecast[forecast < quantile(forecast, 0.95) & forecast > quantile(forecast, 0.05)]
  #fit <- which(fit < quantile(fit, 0.95) & fit > quantile(fit, 0.05))
  diff <- sum(forecast) - sum(initial_data) 
  print(sum(forecast))
  print(sum(initial_data))
  print("-------")
  if(abs(diff) > threshold){
    if(diff > 0){
      return(1)
    }
    else{
      return(-1)
    }
  }
  return(0)
}
temp <- alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',]
temp <- temp[temp$L1 == '8',]
res <- split_stages(temp, 3 * 60, 30, 0.01)
print(unique(res))
[1] 1 2 3 4
Levels: 1 2 3 4
temp <- alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',]
temp <- temp[temp$L1 == '1',]
res <- split_stages(temp, 3 * 60, 30, 0.01)
add_stages <- function(df, time_interval, representative_period, threshold){
  df$stages <- rep(0,nrow(df))
  for(factor in levels(df$L1)){
    df[df$L1 == factor,]$stages <- split_stages( df[df$L1 == factor,], time_interval, representative_period, threshold)
  }
  return(df)
}
temp <- alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',]
temp <- add_stages(temp, 3 * 60, 30, 0.001)
alpha_with_averages <- subset_and_melt(TRUE, TRUE, 'alpha', 'all', TRUE, TRUE)
temp <- alpha_with_averages[alpha_with_averages$waves == 'avg_alpha',]
alpha_stages <- add_stages(temp, 3 * 60, 30, 5)
[1] -35.20688
[1] -34.29825
[1] "-------"
[1] -14.63786
[1] -15.28299
[1] "-------"
[1] 15.32103
[1] 10.06241
[1] "-------"
[1] 6.146795
[1] 82.95732
[1] "-------"
[1] 35.15567
[1] 36.35809
[1] "-------"
[1] 391.2204
[1] 390.8586
[1] "-------"
[1] 571.8857
[1] 536.5056
[1] "-------"
[1] 420.7765
[1] 422.2623
[1] "-------"
[1] 517.0316
[1] 498.9921
[1] "-------"
[1] 366.9362
[1] 416.9336
[1] "-------"
[1] 451.5398
[1] 440.67
[1] "-------"
[1] 468.0502
[1] 484.8621
[1] "-------"
[1] 510.2569
[1] 460.9515
[1] "-------"
[1] 48.10229
[1] 133.7512
[1] "-------"
[1] 98.76786
[1] 97.1298
[1] "-------"
[1] 84.62468
[1] 78.74971
[1] "-------"
[1] 86.0356
[1] 92.70745
[1] "-------"
[1] 5.766955
[1] 58.91794
[1] "-------"
[1] 71.68597
[1] 56.37134
[1] "-------"
[1] 436.6874
[1] 118.4694
[1] "-------"
[1] 81.68036
[1] 81.26119
[1] "-------"
[1] 64.96005
[1] 97.23356
[1] "-------"
[1] 81.21402
[1] 51.12887
[1] "-------"
[1] -2.428206
[1] 71.86342
[1] "-------"
[1] 49.71121
[1] 73.13329
[1] "-------"
[1] 84.41539
[1] 82.1399
[1] "-------"
[1] 67.44729
[1] 91.86051
[1] "-------"
[1] 65.09052
[1] 79.8176
[1] "-------"
[1] 122.6536
[1] 54.5804
[1] "-------"
[1] 57.36476
[1] 71.7172
[1] "-------"
[1] 0.01791189
[1] -1.269861
[1] "-------"
[1] -13.79072
[1] -0.02891286
[1] "-------"
[1] 9.225325
[1] 5.07441
[1] "-------"
[1] 5.871108
[1] -14.28683
[1] "-------"
[1] -0.01042182
[1] 4.490672
[1] "-------"
[1] -19.42542
[1] 35.55241
[1] "-------"
[1] -6.670456
[1] -0.07772321
[1] "-------"
[1] -7.039187e-05
[1] 4.346686
[1] "-------"
[1] 64.52856
[1] -4.243069
[1] "-------"
[1] -0.0002926155
[1] 8.918285
[1] "-------"
[1] 534.1726
[1] 532.2413
[1] "-------"
[1] 496.291
[1] 497.9683
[1] "-------"
[1] 473.2478
[1] 473.1004
[1] "-------"
[1] 194.3603
[1] 463.7927
[1] "-------"
[1] 475.0435
[1] 475.4863
[1] "-------"
[1] 459.2095
[1] 456.1062
[1] "-------"
[1] 465.478
[1] 451.3855
[1] "-------"
[1] 419.1453
[1] 455.8208
[1] "-------"
[1] 451.4211
[1] 450.9958
[1] "-------"
[1] 418.1923
[1] 444.9182
[1] "-------"
the_person <- alpha_stages[alpha_stages$L1 == '1',]
print(unique(the_person$stages))
[1] 1 2
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '2',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '3',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '4',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '5',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '6',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '7',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

the_person <- alpha_stages[alpha_stages$L1 == '8',]
ggplot() +
  geom_line(aes(y = value, x = timestamps, color = as.factor(stages)), data = the_person, alpha = 1) +
  geom_smooth(aes(y = value, x = timestamps), data = the_person, color = "black") +
  scale_x_continuous(breaks = seq(0, 1000, by = 180)) +
  scale_color_brewer(palette = "Blues")

LS0tCnRpdGxlOiAiRUVHIGFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgppbXBvcnRzCmBgYHtyfQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHBzcGxpbmUpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoVFRSKQpyZXF1aXJlKHNtb290aCkKcmVxdWlyZShncmV5Ym94KQpyZXF1aXJlKE1jb21wKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShmb3JlY2FzdCkKYGBgCgoKYGBge3J9CmFkZF9sb2VzcyA8LSBmdW5jdGlvbihkZil7CiAgbG9lc3NfZGYgPC0gZGF0YS5mcmFtZShkZiR0aW1lc3RhbXBzKQogIGZvcihpIGluIG5hbWVzKGRmKSl7CiAgICBpZihncmVwbCgnYWJzb2x1dGUnLCBpKSAmICFncmVwbCgnbG9lc3MnLCBpKSl7CiAgICAgIG5hbWUgPC0gcGFzdGUoImxvZXNzXyIsIGksIHNlcCA9ICIiKQogICAgICBkZlssIG5hbWVdIDwtIGxvZXNzKGRmWyxpXSB+IGRmJHRpbWVzdGFtcHMsIGRhdGEgPSBkZiwgc3Bhbj0wLjY1KSRmaXR0ZWQKICAgIH0KICB9CiAgcmV0dXJuKGRmKQp9CmBgYAoKYGBge3J9CmFkZF9hdmVyYWdlIDwtIGZ1bmN0aW9uKGRmLCB3YXZlKXsKICBuYW1lIDwtIHBhc3RlKCJhdmdfIiwgd2F2ZSwgc2VwID0gIiIpCiAgdGVtcF9kZiA8LSBkZlssbmFtZXMoZGYpICVpbiUgY29sbmFtZXMoZGYpW2dyZXBsKHdhdmUsY29sbmFtZXMoZGYpKSAmICFncmVwbCgibG9lc3MiLGNvbG5hbWVzKGRmKSkgJiAhZ3JlcGwoIjEiLGNvbG5hbWVzKGRmKSkgJiAhZ3JlcGwoIjQiLGNvbG5hbWVzKGRmKSldXQogIHRlbXBfYXZnIDwtIHJvd01lYW5zKHRlbXBfZGYsIGRpbXMgPSAxKQogIGRmWywgbmFtZV0gPC0gdGVtcF9hdmcKICByZXR1cm4oZGYpCn0KYGBgCgoKbG9hZCBkYXRhCmBgYHtyfQppbmV4cF9tZWRpdGF0aW9uX2ZpbGVzID0gc29ydChsaXN0LmZpbGVzKCJmZnRlZC8iLHBhdHRlcm49Il4wX2ZmdGVkX21lZCIpKQppbmV4cF9yZWZlcmVuY2VfZmlsZXMgPSBzb3J0KGxpc3QuZmlsZXMoImZmdGVkLyIscGF0dGVybj0iXjBfZmZ0ZWRfcmVmIikpCmV4cF9tZWRpdGF0aW9uX2ZpbGVzID0gc29ydChsaXN0LmZpbGVzKCJmZnRlZC8iLHBhdHRlcm49Il4xX2ZmdGVkX21lZCIpKQpleHBfcmVmZXJlbmNlX2ZpbGVzID0gc29ydChsaXN0LmZpbGVzKCJmZnRlZC8iLHBhdHRlcm49Il4xX2ZmdGVkX3JlZiIpKQoKCmV4cF9tZWRpdGF0aW9uID0gbGlzdCgpCmZvcihpIGluIDE6bGVuZ3RoKGV4cF9tZWRpdGF0aW9uX2ZpbGVzKSkgewogIGZpbGUgPSBleHBfbWVkaXRhdGlvbl9maWxlc1tpXQogIGV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gcmVhZC5jc3YocGFzdGUoImZmdGVkLyIsIGZpbGUsIHNlcD0iIikpCiAgZXhwX21lZGl0YXRpb25bW2ldXSA8LSBleHBfbWVkaXRhdGlvbltbaV1dW3Jvd1N1bXMoZXhwX21lZGl0YXRpb25bW2ldXSA9PSAiLUluZiIpID09IDAsICwgZHJvcCA9IEZBTFNFXQogIGV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoZXhwX21lZGl0YXRpb25bW2ldXSwgImFscGhhIikKICBleHBfbWVkaXRhdGlvbltbaV1dIDwtIGFkZF9hdmVyYWdlKGV4cF9tZWRpdGF0aW9uW1tpXV0sICJiZXRhIikKICBleHBfbWVkaXRhdGlvbltbaV1dIDwtIGFkZF9hdmVyYWdlKGV4cF9tZWRpdGF0aW9uW1tpXV0sICJnYW1tYSIpCiAgZXhwX21lZGl0YXRpb25bW2ldXSA8LSBhZGRfYXZlcmFnZShleHBfbWVkaXRhdGlvbltbaV1dLCAiZGVsdGEiKQogIGV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoZXhwX21lZGl0YXRpb25bW2ldXSwgInRoZXRhIikKICBleHBfbWVkaXRhdGlvbltbaV1dIDwtIGFkZF9sb2VzcyhleHBfbWVkaXRhdGlvbltbaV1dKQp9CgppbmV4cF9tZWRpdGF0aW9uID0gbGlzdCgpCmZvcihpIGluIDE6bGVuZ3RoKGluZXhwX21lZGl0YXRpb25fZmlsZXMpKSB7CiAgZmlsZSA9IGluZXhwX21lZGl0YXRpb25fZmlsZXNbaV0KICBpbmV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gIHJlYWQuY3N2KHBhc3RlKCJmZnRlZC8iLCBmaWxlLCBzZXA9IiIpKQogIGluZXhwX21lZGl0YXRpb25bW2ldXSA8LSBpbmV4cF9tZWRpdGF0aW9uW1tpXV1bcm93U3VtcyhpbmV4cF9tZWRpdGF0aW9uW1tpXV0gPT0gIi1JbmYiKSA9PSAwLCAsIGRyb3AgPSBGQUxTRV0KICBpbmV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoaW5leHBfbWVkaXRhdGlvbltbaV1dLCAiYWxwaGEiKQogIGluZXhwX21lZGl0YXRpb25bW2ldXSA8LSBhZGRfYXZlcmFnZShpbmV4cF9tZWRpdGF0aW9uW1tpXV0sICJiZXRhIikKICBpbmV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoaW5leHBfbWVkaXRhdGlvbltbaV1dLCAiZ2FtbWEiKQogIGluZXhwX21lZGl0YXRpb25bW2ldXSA8LSBhZGRfYXZlcmFnZShpbmV4cF9tZWRpdGF0aW9uW1tpXV0sICJkZWx0YSIpCiAgaW5leHBfbWVkaXRhdGlvbltbaV1dIDwtIGFkZF9hdmVyYWdlKGluZXhwX21lZGl0YXRpb25bW2ldXSwgInRoZXRhIikKICBpbmV4cF9tZWRpdGF0aW9uW1tpXV0gPC0gYWRkX2xvZXNzKGluZXhwX21lZGl0YXRpb25bW2ldXSkKfQoKZXhwX3JlZmVyZW5jZSA9IGxpc3QoKQpmb3IoaSBpbiAxOmxlbmd0aChleHBfcmVmZXJlbmNlX2ZpbGVzKSkgewogIGZpbGUgPSBleHBfcmVmZXJlbmNlX2ZpbGVzW2ldCiAgZXhwX3JlZmVyZW5jZVtbaV1dIDwtICByZWFkLmNzdihwYXN0ZSgiZmZ0ZWQvIiwgZmlsZSwgc2VwPSIiKSkKICBleHBfcmVmZXJlbmNlW1tpXV0gPC0gZXhwX3JlZmVyZW5jZVtbaV1dW3Jvd1N1bXMoZXhwX3JlZmVyZW5jZVtbaV1dID09ICItSW5mIikgPT0gMCwgLCBkcm9wID0gRkFMU0VdCiAgZXhwX3JlZmVyZW5jZVtbaV1dIDwtIGFkZF9hdmVyYWdlKGV4cF9yZWZlcmVuY2VbW2ldXSwgImFscGhhIikKICBleHBfcmVmZXJlbmNlW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoZXhwX3JlZmVyZW5jZVtbaV1dLCAiYmV0YSIpCiAgZXhwX3JlZmVyZW5jZVtbaV1dIDwtIGFkZF9hdmVyYWdlKGV4cF9yZWZlcmVuY2VbW2ldXSwgImdhbW1hIikKICBleHBfcmVmZXJlbmNlW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoZXhwX3JlZmVyZW5jZVtbaV1dLCAiZGVsdGEiKQogIGV4cF9yZWZlcmVuY2VbW2ldXSA8LSBhZGRfYXZlcmFnZShleHBfcmVmZXJlbmNlW1tpXV0sICJ0aGV0YSIpCiAgZXhwX3JlZmVyZW5jZVtbaV1dIDwtIGFkZF9sb2VzcyhleHBfcmVmZXJlbmNlW1tpXV0pCgp9CgppbmV4cF9yZWZlcmVuY2UgPSBsaXN0KCkKZm9yKGkgaW4gMTpsZW5ndGgoaW5leHBfcmVmZXJlbmNlX2ZpbGVzKSkgewogIGZpbGUgPSBpbmV4cF9yZWZlcmVuY2VfZmlsZXNbaV0KICBpbmV4cF9yZWZlcmVuY2VbW2ldXSA8LSAgcmVhZC5jc3YocGFzdGUoImZmdGVkLyIsIGZpbGUsIHNlcD0iIikpCiAgaW5leHBfcmVmZXJlbmNlW1tpXV0gPC0gaW5leHBfcmVmZXJlbmNlW1tpXV1bcm93U3VtcyhpbmV4cF9yZWZlcmVuY2VbW2ldXSA9PSAiLUluZiIpID09IDAsICwgZHJvcCA9IEZBTFNFXQogIGluZXhwX3JlZmVyZW5jZVtbaV1dIDwtIGFkZF9hdmVyYWdlKGluZXhwX3JlZmVyZW5jZVtbaV1dLCAiYWxwaGEiKQogIGluZXhwX3JlZmVyZW5jZVtbaV1dIDwtIGFkZF9hdmVyYWdlKGluZXhwX3JlZmVyZW5jZVtbaV1dLCAiYmV0YSIpCiAgaW5leHBfcmVmZXJlbmNlW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoaW5leHBfcmVmZXJlbmNlW1tpXV0sICJnYW1tYSIpCiAgaW5leHBfcmVmZXJlbmNlW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoaW5leHBfcmVmZXJlbmNlW1tpXV0sICJkZWx0YSIpCiAgaW5leHBfcmVmZXJlbmNlW1tpXV0gPC0gYWRkX2F2ZXJhZ2UoaW5leHBfcmVmZXJlbmNlW1tpXV0sICJ0aGV0YSIpCiAgaW5leHBfcmVmZXJlbmNlW1tpXV0gPC0gYWRkX2xvZXNzKGluZXhwX3JlZmVyZW5jZVtbaV1dKQoKfQpgYGAKCgpjb252ZXJ0IHRpbWUgZnJvbSBhYnNvbHV0ZSB0byByZWxhdGl2ZQpgYGB7cn0KY29udmVydF90aW1lIDwtIGZ1bmN0aW9uKHRpbWVzdGFtcHMpewogIHRpbWUgPC0gdGltZXN0YW1wcyAtIG1pbih0aW1lc3RhbXBzKQogIHJldHVybih0aW1lKQp9CmBgYAoKCnN1YnNldHRpbmcgZGF0YQpgYGB7cn0Kc3Vic2V0X2FuZF9tZWx0IDwtIGZ1bmN0aW9uKG1lZCwgZXhwLCB3YXZlLCBlbGVjdHJvZGVzLCBtZWx0LCBtZWx0X2FsbCl7CiAgaWYobWVkKXsKICAgIGlmKGV4cCl7CiAgICAgIGRmIDwtIGV4cF9tZWRpdGF0aW9uCiAgICB9CiAgICBlbHNlewogICAgICBkZiA8LSBpbmV4cF9tZWRpdGF0aW9uCiAgICB9CiAgfQogIGVsc2V7CiAgICBpZihleHApewogICAgICBkZiA8LSBleHBfcmVmZXJlbmNlCiAgICB9CiAgICBlbHNlewogICAgICBkZiA8LSBpbmV4cF9yZWZlcmVuY2UKICAgIH0KICB9CgogIGRhdGEgPSBsaXN0KCkKICBmb3IoaSBpbiAxOmxlbmd0aChkZikpIHsKICBkYXRhW1tpXV0gPC0gZGZbW2ldXVssIGdyZXBsKHBhc3RlKCcoJywgd2F2ZSwgJyl8KCcsIGVsZWN0cm9kZXMsICcpfCh0aW1lc3RhbXApJywgc2VwID0gIiIpLCBuYW1lcyhkZltbaV1dKSldCiAgZGF0YVtbaV1dJHRpbWVzdGFtcHMgPC0gY29udmVydF90aW1lKGRhdGFbW2ldXSR0aW1lc3RhbXBzKQogIGlmKG1lbHQpewogICAgZGF0YVtbaV1dIDwtIG1lbHQoZGF0YVtbaV1dLCBpZC52YXJzID0gJ3RpbWVzdGFtcHMnLCB2YXJpYWJsZS5uYW1lID0gJ3dhdmVzJykKICAgIGRhdGFbW2ldXSR3YXZlcyA8LSBhcy5mYWN0b3IoZGF0YVtbaV1dJHdhdmVzKQogIH0KICB9CiAgaWYobWVsdF9hbGwpewogICAgZGF0YSA8LSBtZWx0KGRhdGEsIGlkLnZhcnMgPSBjKCd0aW1lc3RhbXBzJywgJ3dhdmVzJywgJ3ZhbHVlJykpCiAgICBkYXRhJEwxIDwtIGFzLmZhY3RvcihkYXRhJEwxKQogIH0KICAKICByZXR1cm4oZGF0YSkKfQoKYGBgCgp0ZXN0aW5nCmBgYHtyfQp0ZW1wXzIgPC0gc3Vic2V0X2FuZF9tZWx0KEZBTFNFLCBUUlVFLCAiYmV0YSIsICJOb25lIiwgVFJVRSwgVFJVRSkKI2dncGxvdCh0ZW1wXzJbWzFdXSwgYWVzKHRpbWVzdGFtcHMsdmFsdWUpKSArIGdlb21fbGluZShhZXMoY29sb3VyID0gd2F2ZXMpKQpgYGAKCnRoaW5ncyB0byB0aGluayBhYm91dDoKKiBleHRyZW1lIHBvaW50cywgc3Bpa2VzLCBldGMKKiBkaWZmZXJlbnQgc21vb3RoaW5nIHJhdGUKKiBkaWZmZXJlbmNlIGJldHdlZW4gbWVkaXRhdGl2ZSBhbmQgcmVndWxhciBzdGF0ZQoqIGRpZmZlcmVuY2UgYmV0d2VlbiBleHBlcmllbmNlZCBtZWRpdGF0b3JzIGFuZCBuZXdiaWVzCiogaG93IHRvIGRldGVybWluZSB0aGUgbGV2ZWxzIGFuZCBzY2FsZSBpdCBmb3Igb3RoZXJzCiogd2hhdCBoYXBwZW5zIHdoZW4gbWVkaXRhdGlvbiBpcyBzdGFibGUKKiBleHBsb3JlIHRoZSBjb2hlcmVuY2UgYmV0d2VlbiBhbHBoYSBhbmQgdGhldGEgd2F2ZXMKCgpleHBsb3JlIGV4cGVyaWVuY2VkL2luZXhwZXJpZW5jZWQgZGlzdHJpYnV0aW9ucyBvZiBhbHBoYSB3YXZlCmBgYHtyfQphbHBoYV9leHBfbWVkID0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIFRSVUUsICdhbHBoYScsICdBTEwnLCBUUlVFLCBUUlVFKQphbHBoYV9pbmV4cF9tZWQgPSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgRkFMU0UsICdhbHBoYScsICdBTEwnLCBUUlVFLCBUUlVFKQphbHBoYV9leHBfbWVkJGV4cCA8LSAiZXhwZXJpZW5jZWQiCmFscGhhX2V4cF9tZWQkZXhwIDwtIGFzLmZhY3RvcihhbHBoYV9leHBfbWVkJGV4cCkKYWxwaGFfaW5leHBfbWVkJGV4cCA8LSAiaW5leHBlcmllbmNlZCIKYWxwaGFfaW5leHBfbWVkJGV4cCA8LSBhcy5mYWN0b3IoYWxwaGFfaW5leHBfbWVkJGV4cCkKdGVtcCA8LSByYmluZChhbHBoYV9leHBfbWVkLCBhbHBoYV9pbmV4cF9tZWQpCmdncGxvdCh0ZW1wLCBhZXModmFsdWUsIGZpbGwgPSBleHApKSArIAogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC41LCBiaW5zID0gMTAwLCBwb3NpdGlvbiA9ICdpZGVudGl0eScpCmBgYAoKZXhwbG9yZSBleHBlcmllbmNlZC9pbmV4cGVyaWVuY2VkIGRpc3RyaWJ1dGlvbnMgb2YgdGhldGEgd2F2ZQpgYGB7cn0KdGhldGFfZXhwX21lZCA9IHN1YnNldF9hbmRfbWVsdChUUlVFLCBUUlVFLCAndGhldGEnLCAnQUxMJywgVFJVRSwgVFJVRSkKdGhldGFfaW5leHBfbWVkID0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIEZBTFNFLCAndGhldGEnLCAnQUxMJywgVFJVRSwgVFJVRSkKdGhldGFfZXhwX21lZCRleHAgPC0gImV4cGVyaWVuY2VkIgp0aGV0YV9leHBfbWVkJGV4cCA8LSBhcy5mYWN0b3IodGhldGFfZXhwX21lZCRleHApCnRoZXRhX2luZXhwX21lZCRleHAgPC0gImluZXhwZXJpZW5jZWQiCnRoZXRhX2luZXhwX21lZCRleHAgPC0gYXMuZmFjdG9yKHRoZXRhX2luZXhwX21lZCRleHApCnRlbXAgPC0gcmJpbmQodGhldGFfZXhwX21lZCwgdGhldGFfaW5leHBfbWVkKQpnZ3Bsb3QodGVtcCwgYWVzKHZhbHVlLCBmaWxsID0gZXhwKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShhbHBoYSA9IDAuNSwgYmlucyA9IDEwMCwgcG9zaXRpb24gPSAnaWRlbnRpdHknKQpgYGAKCmV4cGxvcmUgZXhwZXJpZW5jZWQvaW5leHBlcmllbmNlZCBkaXN0cmlidXRpb25zIG9mIGJldGEgd2F2ZQpgYGB7cn0KYmV0YV9leHBfbWVkID0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIFRSVUUsICdiZXRhJywgJ0FMTCcsIFRSVUUsIFRSVUUpCmJldGFfaW5leHBfbWVkID0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIEZBTFNFLCAnYmV0YScsICdBTEwnLCBUUlVFLCBUUlVFKQpiZXRhX2V4cF9tZWQkZXhwIDwtICJleHBlcmllbmNlZCIKYmV0YV9leHBfbWVkJGV4cCA8LSBhcy5mYWN0b3IoYmV0YV9leHBfbWVkJGV4cCkKYmV0YV9pbmV4cF9tZWQkZXhwIDwtICJpbmV4cGVyaWVuY2VkIgpiZXRhX2luZXhwX21lZCRleHAgPC0gYXMuZmFjdG9yKGJldGFfaW5leHBfbWVkJGV4cCkKdGVtcCA8LSByYmluZChiZXRhX2V4cF9tZWQsIGJldGFfaW5leHBfbWVkKQpnZ3Bsb3QodGVtcCwgYWVzKHZhbHVlLCBmaWxsID0gZXhwKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShhbHBoYSA9IDAuNSwgYmlucyA9IDEwMCwgcG9zaXRpb24gPSAnaWRlbnRpdHknKQpgYGAKCmV4cGxvcmUgZXhwZXJpZW5jZWQvaW5leHBlcmllbmNlZCBkaXN0cmlidXRpb25zIG9mIGdhbW1hIHdhdmUKYGBge3J9CmdhbW1hX2V4cF9tZWQgPSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgVFJVRSwgJ2dhbW1hJywgJ0FMTCcsIFRSVUUsIFRSVUUpCmdhbW1hX2luZXhwX21lZCA9IHN1YnNldF9hbmRfbWVsdChUUlVFLCBGQUxTRSwgJ2dhbW1hJywgJ0FMTCcsIFRSVUUsIFRSVUUpCmdhbW1hX2V4cF9tZWQkZXhwIDwtICJleHBlcmllbmNlZCIKZ2FtbWFfZXhwX21lZCRleHAgPC0gYXMuZmFjdG9yKGdhbW1hX2V4cF9tZWQkZXhwKQpnYW1tYV9pbmV4cF9tZWQkZXhwIDwtICJpbmV4cGVyaWVuY2VkIgpnYW1tYV9pbmV4cF9tZWQkZXhwIDwtIGFzLmZhY3RvcihnYW1tYV9pbmV4cF9tZWQkZXhwKQp0ZW1wIDwtIHJiaW5kKGdhbW1hX2V4cF9tZWQsIGdhbW1hX2luZXhwX21lZCkKZ2dwbG90KHRlbXAsIGFlcyh2YWx1ZSwgZmlsbCA9IGV4cCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYWxwaGEgPSAwLjUsIGJpbnMgPSAxMDAsIHBvc2l0aW9uID0gJ2lkZW50aXR5JykKYGBgCgpleHBsb3JlIGV4cGVyaWVuY2VkL2luZXhwZXJpZW5jZWQgZGlzdHJpYnV0aW9ucyBvZiBkZWx0YSB3YXZlCmBgYHtyfQpkZWx0YV9leHBfbWVkID0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIFRSVUUsICdkZWx0YScsICdBTEwnLCBUUlVFLCBUUlVFKQpkZWx0YV9pbmV4cF9tZWQgPSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgRkFMU0UsICdkZWx0YScsICdBTEwnLCBUUlVFLCBUUlVFKQpkZWx0YV9leHBfbWVkJGV4cCA8LSAiZXhwZXJpZW5jZWQiCmRlbHRhX2V4cF9tZWQkZXhwIDwtIGFzLmZhY3RvcihkZWx0YV9leHBfbWVkJGV4cCkKZGVsdGFfaW5leHBfbWVkJGV4cCA8LSAiaW5leHBlcmllbmNlZCIKZGVsdGFfaW5leHBfbWVkJGV4cCA8LSBhcy5mYWN0b3IoZGVsdGFfaW5leHBfbWVkJGV4cCkKdGVtcCA8LSByYmluZChkZWx0YV9leHBfbWVkLCBkZWx0YV9pbmV4cF9tZWQpCmdncGxvdCh0ZW1wLCBhZXModmFsdWUsIGZpbGwgPSBleHApKSArIAogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC41LCBiaW5zID0gMTAwLCBwb3NpdGlvbiA9ICdpZGVudGl0eScpCmBgYAoKYGBge3J9CnQudGVzdChuYS5vbWl0KGFscGhhX2V4cF9tZWQkdmFsdWUpLCBuYS5vbWl0KGFscGhhX2luZXhwX21lZCR2YWx1ZSksIHZhci5lcXVhbCA9IFRSVUUpCmBgYAoKCmBgYHtyfQp0X3Rlc3QgPC0gZnVuY3Rpb24od2F2ZSwgbWVkKXsKICB3YXZlX2V4cCA8LSBzdWJzZXRfYW5kX21lbHQobWVkLCBUUlVFLCB3YXZlLCAiQWxsIiwgVFJVRSwgRkFMU0UpCiAgbWVkaWFuc19leHAgPC0gbGlzdCgpCiAgZm9yKGkgaW4gMTpsZW5ndGgod2F2ZV9leHApKXsKICAgIG1lZGlhbnNfZXhwW1tpXV0gPC0gbWVkaWFuKHdhdmVfZXhwW1tpXV0kdmFsdWUpCiAgfQogIHdhdmVfaW5leHAgPC0gc3Vic2V0X2FuZF9tZWx0KG1lZCwgRkFMU0UsIHdhdmUsICJBbGwiLCBUUlVFLCBGQUxTRSkKICBtZWRpYW5zX2luZXhwIDwtIGxpc3QoKQogIGZvcihpIGluIDE6bGVuZ3RoKHdhdmVfaW5leHApKXsKICAgIG1lZGlhbnNfaW5leHBbW2ldXSA8LSBtZWRpYW4od2F2ZV9pbmV4cFtbaV1dJHZhbHVlKQogIH0KICAKICBtZWRpYW5zX2V4cCA8LSB1bmxpc3QobWVkaWFuc19leHAsIHVzZS5uYW1lcz1GQUxTRSkKICBtZWRpYW5zX2luZXhwIDwtIHVubGlzdChtZWRpYW5zX2luZXhwLCB1c2UubmFtZXM9RkFMU0UpCiAgcmV0dXJuKHByaW50KHQudGVzdChtZWRpYW5zX2V4cCwgbWVkaWFuc19pbmV4cCkpKQp9CgpgYGAKCgpgYGB7cn0KdF90ZXN0KCJhbHBoYSIsIFRSVUUpCmBgYAoKYGBge3J9CmEgPC0gdF90ZXN0KCJiZXRhIiwgVFJVRSkKYGBgCgpgYGB7cn0KYSA8LSB0X3Rlc3QoImdhbW1hIiwgVFJVRSkKYGBgCgpgYGB7cn0KYSA8LSB0X3Rlc3QoImRlbHRhIiwgVFJVRSkKYGBgCgpgYGB7cn0KYSA8LSB0X3Rlc3QoInRoZXRhIiwgVFJVRSkKYGBgCgpUaGVyZSBpcyBubyBzaWduaWZpY2FudCBzdGF0aXN0aWNhbCBkaWZmZXJlbmNlIGluIG1lZGlhbnMgYW5kIG1lYW5zIGJldHdlZW4gZXhwZXJpZW5jZWQgYW5kCmluZXhwZXJpZW5jZWQgcGVvcGxlCgpgYGB7cn0KdF90ZXN0X21pbiA8LSBmdW5jdGlvbih3YXZlLCBtZWQpewogIHdhdmVfZXhwIDwtIHN1YnNldF9hbmRfbWVsdChtZWQsIFRSVUUsIHdhdmUsICJBbGwiLCBUUlVFLCBGQUxTRSkKICBtZWRpYW5zX2V4cCA8LSBsaXN0KCkKICBmb3IoaSBpbiAxOmxlbmd0aCh3YXZlX2V4cCkpewogICAgbWVkaWFuc19leHBbW2ldXSA8LSBtaW4od2F2ZV9leHBbW2ldXSR2YWx1ZSkKICB9CiAgd2F2ZV9pbmV4cCA8LSBzdWJzZXRfYW5kX21lbHQobWVkLCBGQUxTRSwgd2F2ZSwgIkFsbCIsIFRSVUUsIEZBTFNFKQogIG1lZGlhbnNfaW5leHAgPC0gbGlzdCgpCiAgZm9yKGkgaW4gMTpsZW5ndGgod2F2ZV9pbmV4cCkpewogICAgbWVkaWFuc19pbmV4cFtbaV1dIDwtIG1pbih3YXZlX2luZXhwW1tpXV0kdmFsdWUpCiAgfQogIAogIG1lZGlhbnNfZXhwIDwtIHVubGlzdChtZWRpYW5zX2V4cCwgdXNlLm5hbWVzPUZBTFNFKQogIG1lZGlhbnNfaW5leHAgPC0gdW5saXN0KG1lZGlhbnNfaW5leHAsIHVzZS5uYW1lcz1GQUxTRSkKICByZXR1cm4ocHJpbnQodC50ZXN0KG1lZGlhbnNfZXhwLCBtZWRpYW5zX2luZXhwKSkpCn0KYGBgCgpgYGB7cn0KYSA8LSB0X3Rlc3RfbWluKCJhbHBoYSIsIFRSVUUpCmEgPC0gdF90ZXN0X21pbigidGhldGEiLCBUUlVFKQphIDwtIHRfdGVzdF9taW4oImdhbW1hIiwgVFJVRSkKYSA8LSB0X3Rlc3RfbWluKCJiZXRhIiwgVFJVRSkKYSA8LSB0X3Rlc3RfbWluKCJkZWx0YSIsIFRSVUUpCmBgYAoKYGBge3J9CnRfdGVzdF9tYXggPC0gZnVuY3Rpb24od2F2ZSwgbWVkKXsKICB3YXZlX2V4cCA8LSBzdWJzZXRfYW5kX21lbHQobWVkLCBUUlVFLCB3YXZlLCAiQWxsIiwgVFJVRSwgRkFMU0UpCiAgbWVkaWFuc19leHAgPC0gbGlzdCgpCiAgZm9yKGkgaW4gMTpsZW5ndGgod2F2ZV9leHApKXsKICAgIG1lZGlhbnNfZXhwW1tpXV0gPC0gbWF4KHdhdmVfZXhwW1tpXV0kdmFsdWUpCiAgfQogIHdhdmVfaW5leHAgPC0gc3Vic2V0X2FuZF9tZWx0KG1lZCwgRkFMU0UsIHdhdmUsICJBbGwiLCBUUlVFLCBGQUxTRSkKICBtZWRpYW5zX2luZXhwIDwtIGxpc3QoKQogIGZvcihpIGluIDE6bGVuZ3RoKHdhdmVfaW5leHApKXsKICAgIG1lZGlhbnNfaW5leHBbW2ldXSA8LSBtYXgod2F2ZV9pbmV4cFtbaV1dJHZhbHVlKQogIH0KICAKICBtZWRpYW5zX2V4cCA8LSB1bmxpc3QobWVkaWFuc19leHAsIHVzZS5uYW1lcz1GQUxTRSkKICBtZWRpYW5zX2luZXhwIDwtIHVubGlzdChtZWRpYW5zX2luZXhwLCB1c2UubmFtZXM9RkFMU0UpCiAgcmV0dXJuKHByaW50KHQudGVzdChtZWRpYW5zX2V4cCwgbWVkaWFuc19pbmV4cCkpKQp9CmBgYAoKYGBge3J9CmEgPC0gdF90ZXN0X21heCgiYWxwaGEiLCBUUlVFKQphIDwtIHRfdGVzdF9tYXgoInRoZXRhIiwgVFJVRSkKYSA8LSB0X3Rlc3RfbWF4KCJnYW1tYSIsIFRSVUUpCmEgPC0gdF90ZXN0X21heCgiYmV0YSIsIFRSVUUpCmEgPC0gdF90ZXN0X21heCgiZGVsdGEiLCBUUlVFKQpgYGAKYGBge3J9CiNnZ3Bsb3QodGVtcCwgYWVzKHZhbHVlLCBmaWxsID0gZXhwKSkgKyAKIyAgZ2VvbV9oaXN0b2dyYW0oYWxwaGEgPSAwLjUsIGJpbnMgPSAxMDAsIHBvc2l0aW9uID0gJ2lkZW50aXR5JykKCmRhdGFfdGVtcCA8LSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgVFJVRSwgJ2FscGhhJywgIkFMTCIsIFRSVUUsIFRSVUUpCgojZ2VvbV9saW5lKGFlcyh5PXRoZXRhX2Fic29sdXRlXzIsIHggPSB0aW1lc3RhbXBzKSwgCiMgICAgICAgZGF0YSA9IHdpdGhvdXRfbmEsIGNvbG9yPWJyZXdlci5wYWwoNCwgIkJsdWVzIilbM10pICsgI2dlb21fc21vb3RoKGFlcyh5PXRoZXRhX2Fic29sdXRlXzIsIHggPSB0aW1lc3RhbXBzKSwgCiMgICAgICAgZGF0YSA9IHdpdGhvdXRfbmEsIGNvbG9yPWJyZXdlci5wYWwoNCwgIkJsdWVzIilbM10sIHNwYW4gPSAwLjAxKSArCmBgYAoKYGBge3J9CgojdGVtcHMgPC0gZGF0YV90ZW1wW2RhdGFfdGVtcCRMMSA9PSAxICYgZGF0YV90ZW1wJHdhdmVzID09ICJhbHBoYV9hYnNvbHV0ZV8xIiwgXQojIGRhdGFfdGVtcCRMMSA9PSAxLAojZGF0YV90ZW1wJHdhdmVzID09ICJhbHBoYV9hYnNvbHV0ZV8xIiwgCgojZGF0YV90ZW1wIDwtIGRhdGFfdGVtcFtkYXRhX3RlbXAkTDEgPT0gMSxdCgp0b19kcmF3IDwtIGRhdGFfdGVtcFtkYXRhX3RlbXAkTDEgPT0gMSAmIGRhdGFfdGVtcCR3YXZlcyA9PSAiYWxwaGFfYWJzb2x1dGVfMSIsIF0KI2dncGxvdChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSBkYXRhX3RlbXAsIGRhdGFfdGVtcCR3YXZlcyA9PSAiYWxwaGFfYWJzb2x1dGVfMSIpICsKCiNnZ3Bsb3QoKSArIAojICBnZW9tX2xpbmUoYWVzKFNNQSh0b19kcmF3JHZhbHVlLCBuPTE1KSwgeCA9IHRvX2RyYXckdGltZXN0YW1wcykpCgojZ2dwbG90KGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IGRhdGFfdGVtcCwgZGF0YV90ZW1wJHdhdmVzID09ICJhbHBoYV9hYnNvbHV0ZV8xIikgKwogICNnZW9tX2xpbmUoKSArCiMgIGdlb21fc21vb3RoKHNwYW4gPSAwLjAwMSwgbGV2ZWwgPSAwLjk1LCBtZXRob2QgPSAnbG9lc3MnKSAKYGBgCgpgYGB7cn0KdGVtcCA8LSBlcyh0b19kcmF3JHZhbHVlLCBoPTE4LCBob2xkb3V0PVRSVUUsIHNpbGVudD1GQUxTRSkKYGBgCgpgYGB7cn0KCmBgYAoKYGBge3J9CiN0b19kcmF3X3BhcnQkc21hIDwtIHNtYSh0b19kcmF3X3BhcnQkdmFsdWUsIG4gPSA1LCB2ID0gMC45KSRmaXR0ZWQKdG9fZHJhd19wYXJ0JGxvZXNzIDwtIGxvZXNzKHZhbHVlIH4gdGltZXN0YW1wcywgZGF0YT10b19kcmF3X3BhcnQsIHNwYW49MC42NSkkZml0dGVkCmBgYAoKYGBge3J9CgpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IHRvX2RyYXdfcGFydCkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IHRvX2RyYXdfcGFydCwgc3BhbiA9IDEsIG4gPSAxNSwgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBsb2VzcywgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gdG9fZHJhd19wYXJ0LCBjb2xvciA9ICdyZWQnKQpgYGAKCgpgYGB7cn0KZ2dwbG90KCkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IHRoZXRhX2V4cF9tZWRbdGhldGFfZXhwX21lZCR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsXSwgc3BhbiA9IDEsIG4gPSAxNSwgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX2xpbmUoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gdGhldGFfZXhwX21lZFt0aGV0YV9leHBfbWVkJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV8yJyxdLCBjb2xvciA9ICdyZWQnLCBhbHBoYSA9IDAuMikgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSB0aGV0YV9leHBfbWVkW3RoZXRhX2V4cF9tZWQkd2F2ZXMgPT0gJ3RoZXRhX2Fic29sdXRlXzInLF0sIGNvbG9yID0gJ2JsYWNrJywgYWxwaGEgPSAwLjIpCmBgYApgYGB7cn0KY3Vycl9kYXRhIDwtIHRoZXRhX2V4cF9tZWRbdGhldGFfZXhwX21lZCRMMSA9PSAnMScsXQoKI1t0aGV0YV9leHBfbWVkJHdhdmVzID09ICd0aGV0YV9hYnNvbHV0ZV8yJyAmIAogICAgCmdncGxvdChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSBjdXJyX2RhdGEpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ3RoZXRhX2Fic29sdXRlXzInLCBdLCBjb2xvciA9ICdyZWQnLCBhbHBoYSA9IDAuNykgKwogIGdlb21fbGluZShkYXRhID0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsXSwgY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDEpCmBgYAoKYGBge3J9CnRlbXAgPC0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsIF0KbG9lc3Nfb3JkZXJlZCA8LSB0ZW1wJHZhbHVlCmxvZXNzX29yZGVyZWQgPC0gc29ydChsb2Vzc19vcmRlcmVkKQptaW4obG9lc3Nfb3JkZXJlZCkKYmFycGxvdChsb2Vzc19vcmRlcmVkKQpgYGAKYGBge3J9CnRlbXAkc3RhdGUgPC0gY3V0KHRlbXAkdmFsdWUsIHF1YW50aWxlKHRlbXAkdmFsdWUsKDA6NSkvNSkpCgpnZ3Bsb3QoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gY3Vycl9kYXRhKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICd0aGV0YV9hYnNvbHV0ZV8yJywgXSwgY29sb3IgPSAnZ3JleScsIGFscGhhID0gMC43KSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV8yJyxdLCBjb2xvciA9ICdibGFjaycsIGFscGhhID0gMSkgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcywgY29sb3IgPSBzdGF0ZSwgc2l6ZSA9IDIpLGRhdGEgPSB0ZW1wLCBhbHBoYSA9IDEpIAogIApgYGAKCgp0aGV0YV8yLCBzZWNvbmQgcGVyc29uCmBgYHtyfQpjdXJyX2RhdGEgPC0gdGhldGFfZXhwX21lZFt0aGV0YV9leHBfbWVkJEwxID09ICcyJyxdCnRlbXAgPC0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsIF0KdGVtcCRzdGF0ZSA8LSBjdXQodGVtcCR2YWx1ZSwgcXVhbnRpbGUodGVtcCR2YWx1ZSwoMDo1KS81KSkKCmdncGxvdChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSBjdXJyX2RhdGEpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ3RoZXRhX2Fic29sdXRlXzInLCBdLCBjb2xvciA9ICdncmV5JywgYWxwaGEgPSAwLjcpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLF0sIGNvbG9yID0gJ2JsYWNrJywgYWxwaGEgPSAxKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzLCBjb2xvciA9IHN0YXRlLCBzaXplID0gMiksZGF0YSA9IHRlbXAsIGFscGhhID0gMSkgCmBgYAoKYGBge3J9CmN1cnJfZGF0YSA8LSB0aGV0YV9leHBfbWVkW3RoZXRhX2V4cF9tZWQkTDEgPT0gJzMnLF0KdGVtcCA8LSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV8yJywgXQp0ZW1wJHN0YXRlIDwtIGN1dCh0ZW1wJHZhbHVlLCBxdWFudGlsZSh0ZW1wJHZhbHVlLCgwOjUpLzUpKQoKZ2dwbG90KGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IGN1cnJfZGF0YSkgKwogIGdlb21fbGluZShkYXRhID0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAndGhldGFfYWJzb2x1dGVfMicsIF0sIGNvbG9yID0gJ2dyZXknLCBhbHBoYSA9IDAuNykgKwogIGdlb21fbGluZShkYXRhID0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsXSwgY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDEpICsKICBnZW9tX2xpbmUoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMsIGNvbG9yID0gc3RhdGUsIHNpemUgPSAyKSxkYXRhID0gdGVtcCwgYWxwaGEgPSAxKSAKYGBgCgpgYGB7cn0KY3Vycl9kYXRhIDwtIHRoZXRhX2V4cF9tZWRbdGhldGFfZXhwX21lZCRMMSA9PSAnNCcsXQp0ZW1wIDwtIGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLCBdCnRlbXAkc3RhdGUgPC0gY3V0KHRlbXAkdmFsdWUsIHF1YW50aWxlKHRlbXAkdmFsdWUsKDA6NSkvNSkpCgpnZ3Bsb3QoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gY3Vycl9kYXRhKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICd0aGV0YV9hYnNvbHV0ZV8yJywgXSwgY29sb3IgPSAnZ3JleScsIGFscGhhID0gMC43KSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV8yJyxdLCBjb2xvciA9ICdibGFjaycsIGFscGhhID0gMSkgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcywgY29sb3IgPSBzdGF0ZSwgc2l6ZSA9IDIpLGRhdGEgPSB0ZW1wLCBhbHBoYSA9IDEpIApgYGAKCmBgYHtyfQpjdXJyX2RhdGEgPC0gdGhldGFfZXhwX21lZFt0aGV0YV9leHBfbWVkJEwxID09ICc2JyxdCnRlbXAgPC0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsIF0KdGVtcCRzdGF0ZSA8LSBjdXQodGVtcCR2YWx1ZSwgcXVhbnRpbGUodGVtcCR2YWx1ZSwoMDo1KS81KSkKCmdncGxvdChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSBjdXJyX2RhdGEpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ3RoZXRhX2Fic29sdXRlXzInLCBdLCBjb2xvciA9ICdncmV5JywgYWxwaGEgPSAwLjcpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLF0sIGNvbG9yID0gJ2JsYWNrJywgYWxwaGEgPSAxKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzLCBjb2xvciA9IHN0YXRlLCBzaXplID0gMiksZGF0YSA9IHRlbXAsIGFscGhhID0gMSkgCmBgYApgYGB7cn0KY3Vycl9kYXRhIDwtIHRoZXRhX2V4cF9tZWRbdGhldGFfZXhwX21lZCRMMSA9PSAnNycsXQp0ZW1wIDwtIGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLCBdCnRlbXAkc3RhdGUgPC0gY3V0KHRlbXAkdmFsdWUsIHF1YW50aWxlKHRlbXAkdmFsdWUsKDA6NSkvNSkpCgpnZ3Bsb3QoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gY3Vycl9kYXRhKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICd0aGV0YV9hYnNvbHV0ZV8yJywgXSwgY29sb3IgPSAnZ3JleScsIGFscGhhID0gMC43KSArCiAgZ2VvbV9saW5lKGRhdGEgPSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV8yJyxdLCBjb2xvciA9ICdibGFjaycsIGFscGhhID0gMSkgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcywgY29sb3IgPSBzdGF0ZSwgc2l6ZSA9IDIpLGRhdGEgPSB0ZW1wLCBhbHBoYSA9IDEpIApgYGAKCmBgYHtyfQpjdXJyX2RhdGEgPC0gdGhldGFfZXhwX21lZFt0aGV0YV9leHBfbWVkJEwxID09ICc4JyxdCnRlbXAgPC0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsIF0KdGVtcCRzdGF0ZSA8LSBjdXQodGVtcCR2YWx1ZSwgcXVhbnRpbGUodGVtcCR2YWx1ZSwoMDo1KS81KSkKCmdncGxvdChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSBjdXJyX2RhdGEpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ3RoZXRhX2Fic29sdXRlXzInLCBdLCBjb2xvciA9ICdncmV5JywgYWxwaGEgPSAwLjcpICsKICBnZW9tX2xpbmUoZGF0YSA9IGN1cnJfZGF0YVtjdXJyX2RhdGEkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLF0sIGNvbG9yID0gJ2JsYWNrJywgYWxwaGEgPSAxKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzLCBjb2xvciA9IHN0YXRlLCBzaXplID0gMiksZGF0YSA9IHRlbXAsIGFscGhhID0gMSkgCmBgYAoKYGBge3J9CmN1cnJfZGF0YSA8LSBhbHBoYV9leHBfbWVkW3RoZXRhX2V4cF9tZWQkTDEgPT0gJzEnLF0KdGVtcCA8LSBjdXJyX2RhdGFbY3Vycl9kYXRhJHdhdmVzID09ICdsb2Vzc19hbHBoYV9hYnNvbHV0ZV8yJywgXQp0ZW1wJHN0YXRlIDwtIGN1dCh0ZW1wJHZhbHVlLCBxdWFudGlsZSh0ZW1wJHZhbHVlLCgwOjUpLzUpKQoKZ2dwbG90KGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IGN1cnJfZGF0YSkgKwogIGdlb21fbGluZShkYXRhID0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnYWxwaGFfYWJzb2x1dGVfMicsIF0sIGNvbG9yID0gJ2dyZXknLCBhbHBoYSA9IDAuNykgKwogIGdlb21fbGluZShkYXRhID0gY3Vycl9kYXRhW2N1cnJfZGF0YSR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfMicsXSwgY29sb3IgPSAnYmxhY2snLCBhbHBoYSA9IDEpICsKICBnZW9tX2xpbmUoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMsIGNvbG9yID0gc3RhdGUsIHNpemUgPSAyKSxkYXRhID0gdGVtcCwgYWxwaGEgPSAxKSAKYGBgCgpgYGB7cn0KCmBgYAoKYGBge3J9CmFscGhhXzJfYWxsX2V4cCA8LSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgVFJVRSwgJ2FscGhhJywgJ0FsbCcsIFRSVUUsIFRSVUUpCgpnZ3Bsb3QoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUpLCBkYXRhID0gYWxwaGFfMl9hbGxfZXhwW2FscGhhXzJfYWxsX2V4cCR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfMicsXSkgKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBMMSkpICsKICBnZ3RpdGxlKCJhbHBoYSAyLCBleHAiKQpgYGAKCmBgYHtyfQphbHBoYV8yX2FsbF9leHAgPC0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIFRSVUUsICdhbHBoYScsICdBbGwnLCBUUlVFLCBUUlVFKQoKZ2dwbG90KGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlKSwgZGF0YSA9IGFscGhhXzJfYWxsX2V4cFthbHBoYV8yX2FsbF9leHAkd2F2ZXMgPT0gJ2xvZXNzX2FscGhhX2Fic29sdXRlXzEnLF0pICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gTDEpKSArCiAgZ2d0aXRsZSgiYWxwaGEgMSwgZXhwIikKYGBgCgpgYGB7cn0KYWxwaGFfMl9hbGxfZXhwIDwtIHN1YnNldF9hbmRfbWVsdChUUlVFLCBUUlVFLCAnYWxwaGEnLCAnQWxsJywgVFJVRSwgVFJVRSkKCmdncGxvdChhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSksIGRhdGEgPSBhbHBoYV8yX2FsbF9leHBbYWxwaGFfMl9hbGxfZXhwJHdhdmVzID09ICdsb2Vzc19hbHBoYV9hYnNvbHV0ZV8zJyxdKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IEwxKSkgKwogIGdndGl0bGUoImFscGhhIDMsIGV4cCIpCmBgYAoKYGBge3J9CmFscGhhXzJfYWxsX2V4cCA8LSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgVFJVRSwgJ2FscGhhJywgJ0FsbCcsIFRSVUUsIFRSVUUpCgpnZ3Bsb3QoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUpLCBkYXRhID0gYWxwaGFfMl9hbGxfZXhwW2FscGhhXzJfYWxsX2V4cCR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfNCcsXSkgKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBMMSkpICsKICBnZ3RpdGxlKCJhbHBoYSA0LCBleHAiKQpgYGAKCmBgYHtyfQphbHBoYV8yX2FsbF9leHAgPC0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIEZBTFNFLCAnYWxwaGEnLCAnQWxsJywgVFJVRSwgVFJVRSkKCmdncGxvdChhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSksIGRhdGEgPSBhbHBoYV8yX2FsbF9leHBbYWxwaGFfMl9hbGxfZXhwJHdhdmVzID09ICdsb2Vzc19hbHBoYV9hYnNvbHV0ZV8yJyxdKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IEwxKSkgKwogIGdndGl0bGUoImFscGhhIDIsIGluZXhwIikKYGBgCgpgYGB7cn0KZ2dwbG90KGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlKSwgZGF0YSA9IGFscGhhXzJfYWxsX2V4cFthbHBoYV8yX2FsbF9leHAkd2F2ZXMgPT0gJ2xvZXNzX2FscGhhX2Fic29sdXRlXzEnLF0pICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gTDEpKSArCiAgZ2d0aXRsZSgiYWxwaGEgMSwgaW5leHAiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUpLCBkYXRhID0gYWxwaGFfMl9hbGxfZXhwW2FscGhhXzJfYWxsX2V4cCR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfMycsXSkgKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBMMSkpICsKICBnZ3RpdGxlKCJhbHBoYSAzLCBpbmV4cCIpCmBgYAoKYGBge3J9CmdncGxvdChhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSksIGRhdGEgPSBhbHBoYV8yX2FsbF9leHBbYWxwaGFfMl9hbGxfZXhwJHdhdmVzID09ICdsb2Vzc19hbHBoYV9hYnNvbHV0ZV80JyxdKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IEwxKSkgKwogIGdndGl0bGUoImFscGhhIDQsIGluZXhwIikKYGBgCgpgYGB7cn0KdGVtcCA8LSBzdWJzZXRfYW5kX21lbHQoVFJVRSwgVFJVRSwgJ3RoZXRhJywgJ0FsbCcsIFRSVUUsIFRSVUUpCgpnZ3Bsb3QoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUpLCBkYXRhID0gdGVtcFt0ZW1wJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV8xJyxdKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IEwxKSkgKwogIGdndGl0bGUoInRoZXRhIDEsIGV4cCIpCmBgYAoKYGBge3J9CmdncGxvdChhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSksIGRhdGEgPSB0ZW1wW3RlbXAkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLF0pICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gTDEpKSArCiAgZ2d0aXRsZSgidGhldGEgMiwgZXhwIikKYGBgCgpgYGB7cn0KZ2dwbG90KGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMycsXSkgKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBMMSkpICsKICBnZ3RpdGxlKCJ0aGV0YSAzLCBleHAiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUpLCBkYXRhID0gdGVtcFt0ZW1wJHdhdmVzID09ICdsb2Vzc190aGV0YV9hYnNvbHV0ZV80JyxdKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IEwxKSkgKwogIGdndGl0bGUoInRoZXRhIDQsIGV4cCIpCmBgYAoKYGBge3J9CnRlbXAgPC0gc3Vic2V0X2FuZF9tZWx0KFRSVUUsIFRSVUUsICdhbHBoYScsICd0aGV0YScsIFRSVUUsIFRSVUUpCgpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMScsXSwgIHNpemUgPSAxKSArCiAgZ2d0aXRsZSgidGhldGEgMSBhbmQgYWxwaGEgMSwgZXhwIikgKwogIGdlb21fbGluZShhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSwgY29sb3IgPSBMMSksIGRhdGEgPSB0ZW1wW3RlbXAkd2F2ZXMgPT0gJ2xvZXNzX2FscGhhX2Fic29sdXRlXzEnLF0sIGxpbmV0eXBlID0gJ2RvdHRlZCcsIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU3BlY3RyYWwiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMicsXSwgIHNpemUgPSAxKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfMicsXSwgbGluZXR5cGUgPSAnZG90dGVkJywgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpICsKICBnZ3RpdGxlKCJ0aGV0YSAyIGFuZCBhbHBoYSAyLCBleHAiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfMycsXSwgIHNpemUgPSAxKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfMycsXSwgbGluZXR5cGUgPSAnZG90dGVkJywgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpICsKICBnZ3RpdGxlKCJ0aGV0YSAzIGFuZCBhbHBoYSAzLCBleHAiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfdGhldGFfYWJzb2x1dGVfNCcsXSwgIHNpemUgPSAxKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRlbXBbdGVtcCR3YXZlcyA9PSAnbG9lc3NfYWxwaGFfYWJzb2x1dGVfNCcsXSwgbGluZXR5cGUgPSAnZG90dGVkJywgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpICsKICBnZ3RpdGxlKCJ0aGV0YSA0IGFuZCBhbHBoYSA0LCBleHAiKQpgYGAKCmBgYHtyfQphbHBoYV93aXRoX2F2ZXJhZ2VzIDwtIHN1YnNldF9hbmRfbWVsdChUUlVFLCBUUlVFLCAnYWxwaGEnLCAnYWxsJywgVFJVRSwgVFJVRSkKCmdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUsIGNvbG9yID0gTDEpLCBkYXRhID0gYWxwaGFfd2l0aF9hdmVyYWdlc1thbHBoYV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdhbHBoYV9hYnNvbHV0ZV8yJyxdLCAgc2l6ZSA9IDEpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUsIGNvbG9yID0gTDEpLCBkYXRhID0gYWxwaGFfd2l0aF9hdmVyYWdlc1thbHBoYV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdsb2Vzc19hbHBoYV9hYnNvbHV0ZV8yJyxdLCBsaW5ldHlwZSA9ICdkb3R0ZWQnLCBzaXplID0gMSkgKwogIGdlb21fbGluZShhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSwgY29sb3IgPSBMMSksIGRhdGEgPSBhbHBoYV93aXRoX2F2ZXJhZ2VzW2FscGhhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2F2Z19hbHBoYScsXSwgbGluZXR5cGUgPSAnZG90dGVkJywgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpICsKICBnZ3RpdGxlKCJhbHBoYSAyIGFsbCB0b2dldGhlciwgZXhwIikKYGBgCgpgYGB7cn0KZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSwgY29sb3IgPSBMMSksIGRhdGEgPSBhbHBoYV93aXRoX2F2ZXJhZ2VzW2FscGhhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2F2Z19hbHBoYScsXSwgc2l6ZSA9IDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU3BlY3RyYWwiKSArCiAgZ2d0aXRsZSgiYWxwaGEgYXZlcmFnZXMiKQpgYGAKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUsIGNvbG9yID0gTDEpLCBkYXRhID0gYWxwaGFfd2l0aF9hdmVyYWdlc1thbHBoYV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdhdmdfYWxwaGEnLF0sIHNpemUgPSAxLCBhbHBoYSA9IDAuMikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikgKwogIGdlb21fc21vb3RoKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IGFscGhhX3dpdGhfYXZlcmFnZXNbYWxwaGFfd2l0aF9hdmVyYWdlcyR3YXZlcyA9PSAnYXZnX2FscGhhJyxdLCBzaXplID0gMSkgKwogIGdndGl0bGUoImFscGhhIGF2ZXJhZ2VzIHdpdGggc21vb3RoaW5nIikKYGBgCgoKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX3Ntb290aChhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSwgY29sb3IgPSBMMSksIGRhdGEgPSBhbHBoYV93aXRoX2F2ZXJhZ2VzW2FscGhhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2F2Z19hbHBoYScsXSwgc2l6ZSA9IDAuNSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikgKwogIGdndGl0bGUoImFscGhhIGF2ZXJhZ2VzIHdpdGggc21vb3RoaW5nIikKYGBgCgpgYGB7cn0KZ2dwbG90KCkgKwogIGdlb21fc21vb3RoKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IGFscGhhX3dpdGhfYXZlcmFnZXNbYWxwaGFfd2l0aF9hdmVyYWdlcyR3YXZlcyA9PSAnYXZnX2FscGhhJyxdLCBzaXplID0gMC41KSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUsIGNvbG9yID0gTDEpLCBkYXRhID0gYWxwaGFfd2l0aF9hdmVyYWdlc1thbHBoYV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdsb2Vzc19hbHBoYV9hYnNvbHV0ZV8yJyxdLCBzaXplID0gMSwgYWxwaGEgPSAxKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU3BlY3RyYWwiKSArCiAgZ2d0aXRsZSgiYWxwaGEgYXZlcmFnZXMgd2l0aCBzbW9vdGhpbmcgVlMgYWxwaGEgMiAoYm9sZCkiKQpgYGAKCmBgYHtyfQp0aGV0YV93aXRoX2F2ZXJhZ2VzIDwtIHN1YnNldF9hbmRfbWVsdChUUlVFLCBUUlVFLCAndGhldGEnLCAnYWxsJywgVFJVRSwgVFJVRSkKYGBgCgpgYGB7cn0KZ2dwbG90KCkgKwogIGdlb21fc21vb3RoKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IHRoZXRhX3dpdGhfYXZlcmFnZXNbdGhldGFfd2l0aF9hdmVyYWdlcyR3YXZlcyA9PSAnYXZnX3RoZXRhJyxdLCBzaXplID0gMC41KSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU3BlY3RyYWwiKSArCiAgZ2d0aXRsZSgidGhldGEgYXZlcmFnZXMgd2l0aCBzbW9vdGhpbmciKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSB0aW1lc3RhbXBzLCB5ID0gdmFsdWUsIGNvbG9yID0gTDEpLCBkYXRhID0gdGhldGFfd2l0aF9hdmVyYWdlc1t0aGV0YV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdhdmdfdGhldGEnLF0sIHNpemUgPSAwLjUpICsKICAgIGdlb21fbGluZShhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSwgY29sb3IgPSBMMSksIGRhdGEgPSB0aGV0YV93aXRoX2F2ZXJhZ2VzW3RoZXRhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2xvZXNzX3RoZXRhX2Fic29sdXRlXzInLF0sIHNpemUgPSAxLCBhbHBoYSA9IDEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpICsKICBnZ3RpdGxlKCJ0aGV0YSBhdmVyYWdlcyB3aXRoIHNtb290aGluZyBWUyB0aGV0YSAyIChib2xkKSIpCmBgYAoKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX3Ntb290aChhZXMoeCA9IHRpbWVzdGFtcHMsIHkgPSB2YWx1ZSwgY29sb3IgPSBMMSksIGRhdGEgPSB0aGV0YV93aXRoX2F2ZXJhZ2VzW3RoZXRhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2F2Z190aGV0YScsXSwgc2l6ZSA9IDAuNSkgKwogIGdlb21fc21vb3RoKGFlcyh4ID0gdGltZXN0YW1wcywgeSA9IHZhbHVlLCBjb2xvciA9IEwxKSwgZGF0YSA9IGFscGhhX3dpdGhfYXZlcmFnZXNbYWxwaGFfd2l0aF9hdmVyYWdlcyR3YXZlcyA9PSAnYXZnX2FscGhhJyxdLCBzaXplID0gMSkgKwogIAogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikgKwogIGdndGl0bGUoInRoZXRhIGF2ZXJhZ2VzIFZTIGFscGhhIGF2ZXJhZ2VzIChib2xkKSIpCmBgYAoKYGBge3J9CnNwbGl0X3N0YWdlcyA8LSBmdW5jdGlvbihkZiwgdGltZV9pbnRlcnZhbCwgcmVwcmVzZW50YXRpdmVfcGVyaW9kLCB0aHJlc2hvbGQpewogIGN1cnJlbnRfdGltZSA8LSAwCiAgY3VycmVudF9zdGFnZSA8LSAxCiAgZGYkc3RhZ2VzIDwtIHJlcCgwLG5yb3coZGYpKQogIGRmJHN0YWdlc1tkZiR0aW1lc3RhbXBzIDwgY3VycmVudF90aW1lICsgdGltZV9pbnRlcnZhbF0gPC0gY3VycmVudF9zdGFnZSAjZmlyc3QgMyBtaW51dGVzCiAgd2hpbGUoVFJVRSl7CiAgICBpZihjdXJyZW50X3RpbWUgKyB0aW1lX2ludGVydmFsICsgMSA+IG1heChkZiR0aW1lc3RhbXBzKSl7CiAgICAgIGJyZWFrCiAgICB9CiAgICByZXByX2RmIDwtIGRmWyhkZiR0aW1lc3RhbXBzIDwgKGN1cnJlbnRfdGltZSArIHRpbWVfaW50ZXJ2YWwpICYgZGYkdGltZXN0YW1wcyA+IChjdXJyZW50X3RpbWUgKyB0aW1lX2ludGVydmFsIC0gcmVwcmVzZW50YXRpdmVfcGVyaW9kKSksXQogICAgbmV3X3N0YWdlX3NpZ24gPC0gbmV4dF9zdGFnZShyZXByX2RmLCB0aHJlc2hvbGQpICNkZWZpbmluZyBhIG5ldyBzdGFnZSBsZXZlbAogICAgaWYobmV3X3N0YWdlX3NpZ24gPiAwKXsKICAgICAgY3VycmVudF9zdGFnZSA8LSBtaW4oY3VycmVudF9zdGFnZSArIDEsIDUpCiAgICB9CiAgICBpZihuZXdfc3RhZ2Vfc2lnbiA8IDApewogICAgICBjdXJyZW50X3N0YWdlIDwtIG1heChjdXJyZW50X3N0YWdlIC0gMSwgMSkKICAgIH0KICAgICNzZXQgYSBuZXcgc3RhZ2UgaW4gdGhlIGRmCiAgICBkZlsoZGYkdGltZXN0YW1wcyA8IChjdXJyZW50X3RpbWUgKyAyICogdGltZV9pbnRlcnZhbCkgJiBkZiR0aW1lc3RhbXBzID4gKGN1cnJlbnRfdGltZSArIHRpbWVfaW50ZXJ2YWwpKSxdJHN0YWdlcyA8LSBjdXJyZW50X3N0YWdlCiAgICBjdXJyZW50X3RpbWUgPC0gY3VycmVudF90aW1lICsgdGltZV9pbnRlcnZhbAogIH0KICBkZiRzdGFnZXMgPC0gYXMuZmFjdG9yKGRmJHN0YWdlcykKICByZXR1cm4oZGYkc3RhZ2VzKQp9CmBgYAoKYGBge3J9Cm5leHRfc3RhZ2UgPC0gZnVuY3Rpb24oZGYsIHRocmVzaG9sZCl7CiAgZml0IDwtIGF1dG8uYXJpbWEoZGYkdmFsdWUpCiAgZm9yZWNhc3QgPC0gcHJlZGljdChmaXQsIGxlbmd0aChkZiR2YWx1ZSkpCiAgaW5pdGlhbF9kYXRhIDwtIGRmWyhkZiR2YWx1ZSA8IHF1YW50aWxlKGRmJHZhbHVlLCAwLjk1KSAmIGRmJHZhbHVlID4gcXVhbnRpbGUoZGYkdmFsdWUsIDAuMDUpKSwgXSR2YWx1ZQogIGZvcmVjYXN0IDwtIGZvcmVjYXN0JHByZWQKICBmb3JlY2FzdCA8LSBmb3JlY2FzdFtmb3JlY2FzdCA8IHF1YW50aWxlKGZvcmVjYXN0LCAwLjk1KSAmIGZvcmVjYXN0ID4gcXVhbnRpbGUoZm9yZWNhc3QsIDAuMDUpXQogICNmaXQgPC0gd2hpY2goZml0IDwgcXVhbnRpbGUoZml0LCAwLjk1KSAmIGZpdCA+IHF1YW50aWxlKGZpdCwgMC4wNSkpCiAgZGlmZiA8LSBzdW0oZm9yZWNhc3QpIC0gc3VtKGluaXRpYWxfZGF0YSkgCiAgcHJpbnQoc3VtKGZvcmVjYXN0KSkKICBwcmludChzdW0oaW5pdGlhbF9kYXRhKSkKICBwcmludCgiLS0tLS0tLSIpCiAgaWYoYWJzKGRpZmYpID4gdGhyZXNob2xkKXsKICAgIGlmKGRpZmYgPiAwKXsKICAgICAgcmV0dXJuKDEpCiAgICB9CiAgICBlbHNlewogICAgICByZXR1cm4oLTEpCiAgICB9CiAgfQogIHJldHVybigwKQp9CmBgYAoKYGBge3J9CnRlbXAgPC0gYWxwaGFfd2l0aF9hdmVyYWdlc1thbHBoYV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdhdmdfYWxwaGEnLF0KdGVtcCA8LSB0ZW1wW3RlbXAkTDEgPT0gJzgnLF0KcmVzIDwtIHNwbGl0X3N0YWdlcyh0ZW1wLCAzICogNjAsIDMwLCAwLjAxKQpwcmludCh1bmlxdWUocmVzKSkKYGBgCgpgYGB7cn0KdGVtcCA8LSBhbHBoYV93aXRoX2F2ZXJhZ2VzW2FscGhhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2F2Z19hbHBoYScsXQp0ZW1wIDwtIHRlbXBbdGVtcCRMMSA9PSAnMScsXQpyZXMgPC0gc3BsaXRfc3RhZ2VzKHRlbXAsIDMgKiA2MCwgMzAsIDAuMDEpCmBgYAoKYGBge3J9CmFkZF9zdGFnZXMgPC0gZnVuY3Rpb24oZGYsIHRpbWVfaW50ZXJ2YWwsIHJlcHJlc2VudGF0aXZlX3BlcmlvZCwgdGhyZXNob2xkKXsKICBkZiRzdGFnZXMgPC0gcmVwKDAsbnJvdyhkZikpCiAgZm9yKGZhY3RvciBpbiBsZXZlbHMoZGYkTDEpKXsKICAgIGRmW2RmJEwxID09IGZhY3RvcixdJHN0YWdlcyA8LSBzcGxpdF9zdGFnZXMoIGRmW2RmJEwxID09IGZhY3RvcixdLCB0aW1lX2ludGVydmFsLCByZXByZXNlbnRhdGl2ZV9wZXJpb2QsIHRocmVzaG9sZCkKICB9CiAgcmV0dXJuKGRmKQp9CmBgYAoKYGBge3J9CnRlbXAgPC0gYWxwaGFfd2l0aF9hdmVyYWdlc1thbHBoYV93aXRoX2F2ZXJhZ2VzJHdhdmVzID09ICdhdmdfYWxwaGEnLF0KdGVtcCA8LSBhZGRfc3RhZ2VzKHRlbXAsIDMgKiA2MCwgMzAsIDAuMDAxKQpgYGAKCmBgYHtyfQphbHBoYV93aXRoX2F2ZXJhZ2VzIDwtIHN1YnNldF9hbmRfbWVsdChUUlVFLCBUUlVFLCAnYWxwaGEnLCAnYWxsJywgVFJVRSwgVFJVRSkKdGVtcCA8LSBhbHBoYV93aXRoX2F2ZXJhZ2VzW2FscGhhX3dpdGhfYXZlcmFnZXMkd2F2ZXMgPT0gJ2F2Z19hbHBoYScsXQphbHBoYV9zdGFnZXMgPC0gYWRkX3N0YWdlcyh0ZW1wLCAzICogNjAsIDMwLCA1KQoKdGhlX3BlcnNvbiA8LSBhbHBoYV9zdGFnZXNbYWxwaGFfc3RhZ2VzJEwxID09ICcxJyxdCnByaW50KHVuaXF1ZSh0aGVfcGVyc29uJHN0YWdlcykpCgpgYGAKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzLCBjb2xvciA9IGFzLmZhY3RvcihzdGFnZXMpKSwgZGF0YSA9IHRoZV9wZXJzb24sIGFscGhhID0gMSkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IHRoZV9wZXJzb24sIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAwMCwgYnkgPSAxODApKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKQpgYGAKCmBgYHtyfQp0aGVfcGVyc29uIDwtIGFscGhhX3N0YWdlc1thbHBoYV9zdGFnZXMkTDEgPT0gJzInLF0KCmdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMsIGNvbG9yID0gYXMuZmFjdG9yKHN0YWdlcykpLCBkYXRhID0gdGhlX3BlcnNvbiwgYWxwaGEgPSAxKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gdGhlX3BlcnNvbiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwLCBieSA9IDE4MCkpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIpCmBgYAoKYGBge3J9CnRoZV9wZXJzb24gPC0gYWxwaGFfc3RhZ2VzW2FscGhhX3N0YWdlcyRMMSA9PSAnMycsXQoKZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcywgY29sb3IgPSBhcy5mYWN0b3Ioc3RhZ2VzKSksIGRhdGEgPSB0aGVfcGVyc29uLCBhbHBoYSA9IDEpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSB0aGVfcGVyc29uLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwMDAsIGJ5ID0gMTgwKSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkJsdWVzIikKYGBgCgpgYGB7cn0KdGhlX3BlcnNvbiA8LSBhbHBoYV9zdGFnZXNbYWxwaGFfc3RhZ2VzJEwxID09ICc0JyxdCgpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzLCBjb2xvciA9IGFzLmZhY3RvcihzdGFnZXMpKSwgZGF0YSA9IHRoZV9wZXJzb24sIGFscGhhID0gMSkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IHRoZV9wZXJzb24sIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAwMCwgYnkgPSAxODApKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKQpgYGAKYGBge3J9CnRoZV9wZXJzb24gPC0gYWxwaGFfc3RhZ2VzW2FscGhhX3N0YWdlcyRMMSA9PSAnNScsXQoKZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcywgY29sb3IgPSBhcy5mYWN0b3Ioc3RhZ2VzKSksIGRhdGEgPSB0aGVfcGVyc29uLCBhbHBoYSA9IDEpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSB0aGVfcGVyc29uLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwMDAsIGJ5ID0gMTgwKSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkJsdWVzIikKYGBgCgpgYGB7cn0KdGhlX3BlcnNvbiA8LSBhbHBoYV9zdGFnZXNbYWxwaGFfc3RhZ2VzJEwxID09ICc2JyxdCgpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzLCBjb2xvciA9IGFzLmZhY3RvcihzdGFnZXMpKSwgZGF0YSA9IHRoZV9wZXJzb24sIGFscGhhID0gMSkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gdmFsdWUsIHggPSB0aW1lc3RhbXBzKSwgZGF0YSA9IHRoZV9wZXJzb24sIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTAwMCwgYnkgPSAxODApKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKQpgYGAKCmBgYHtyfQp0aGVfcGVyc29uIDwtIGFscGhhX3N0YWdlc1thbHBoYV9zdGFnZXMkTDEgPT0gJzcnLF0KCmdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMsIGNvbG9yID0gYXMuZmFjdG9yKHN0YWdlcykpLCBkYXRhID0gdGhlX3BlcnNvbiwgYWxwaGEgPSAxKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB2YWx1ZSwgeCA9IHRpbWVzdGFtcHMpLCBkYXRhID0gdGhlX3BlcnNvbiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxMDAwLCBieSA9IDE4MCkpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIpCmBgYAoKYGBge3J9CnRoZV9wZXJzb24gPC0gYWxwaGFfc3RhZ2VzW2FscGhhX3N0YWdlcyRMMSA9PSAnOCcsXQoKZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcywgY29sb3IgPSBhcy5mYWN0b3Ioc3RhZ2VzKSksIGRhdGEgPSB0aGVfcGVyc29uLCBhbHBoYSA9IDEpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHZhbHVlLCB4ID0gdGltZXN0YW1wcyksIGRhdGEgPSB0aGVfcGVyc29uLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEwMDAsIGJ5ID0gMTgwKSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkJsdWVzIikKYGBgCgo=